# IndexedDiff.java

    package org.codefilarete.stalactite.engine.diff;

    import java.util.Collection;
    import java.util.HashSet;
    import java.util.Objects;
    import java.util.Set;

    /**
     * A specialized version of {@link AbstractDiff} for indexed {@link java.util.Collection} because it keeps indexes.
     * Result of a comparison made by {@link CollectionDiffer#diffOrdered(Collection, Collection)}.
     *
     * @author Guillaume Mary
     */
    public class IndexedDiff<C> extends AbstractDiff<C> {

    	private final Set<Integer> sourceIndexes;

    	private final Set<Integer> replacerIndexes;

    	/**
    	 * Constructor without given index (minimal constructor).
    	 * Indexes may be added later with {@link #addReplacerIndex(int)} and {@link #addSourceIndex(int)}
    	 *
    	 * @param state the kind of difference
    	 * @param sourceInstance initial instance
    	 * @param replacingInstance replacing instance (may differ from source on attributes except id)
    	 */
    	public IndexedDiff(State state, C sourceInstance, C replacingInstance) {
    		this(state, sourceInstance, replacingInstance, new HashSet<>(), new HashSet<>());
    	}

    	public IndexedDiff(State state, C sourceInstance, C replacingInstance,
    					   Set<Integer> sourceIndexes, Set<Integer> replacerIndexes) {
    		super(state, sourceInstance, replacingInstance);
    		this.sourceIndexes = sourceIndexes;
    		this.replacerIndexes = replacerIndexes;
    	}

    	public Set<Integer> getSourceIndexes() {
    		return sourceIndexes;
    	}

    	public IndexedDiff addSourceIndex(int index) {
    		this.sourceIndexes.add(index);
    		return this;
    	}

    	public Set<Integer> getReplacerIndexes() {
    		return replacerIndexes;
    	}

    	public IndexedDiff addReplacerIndex(int index) {
    		this.replacerIndexes.add(index);
    		return this;
    	}

    	/**
    	 * Implemented for the {@link CollectionDiffer#diffOrdered(Collection, Collection)} method algorithm
    	 *
    	 * @param o any other object
    	 * @return true when source and replacing instances are equal (indexes are not taken into account)
    	 */
    	@Override
    	public boolean equals(Object o) {
    		if (this == o) return true;
    		if (!(o instanceof IndexedDiff)) return false;
    		IndexedDiff that = (IndexedDiff) o;
    		return Objects.equals(getSourceInstance(), that.getSourceInstance())
    				&& Objects.equals(getReplacingInstance(), that.getReplacingInstance())
     		;
    	}

    	/**
    	 * @return a hash of source and replacing instances, based on same principle as {@link #equals(Object)}
    	 */
    	@Override
    	public int hashCode() {
    		return Objects.hash(getSourceInstance(), getReplacingInstance());
    	}
    }